package com.ldj.tim.server.util;

import com.ldj.tim.common.constant.CacheConstants;
import com.ldj.tim.common.pojo.BasicMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * @author majinhui
 * @description
 * @create 2024/11/12 15:15
 **/
@Component
public class OfflineMessageUtil {
    @Autowired
    private RedisTemplate<String, BasicMessage> redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${msg.offline.cache-size:10}")
    private Integer cacheSize;

    // 存储离线消息
    // 使用 ZADD 命令将消息 ID 作为 score，消息内容作为 value
    public void addMessageToQueue(Long receiverId, String senderId, BasicMessage msg) {
        String key = CacheConstants.OFFLINE_MSG + receiverId + ":" + senderId;
        //记录发送离线消息的用户
        stringRedisTemplate.opsForSet().add("offline_sender_" + receiverId, senderId);
        //记录离线消息
        redisTemplate.opsForZSet().add(key, msg, msg.getTimestamp());
        //todo 不要每次都检查浪费性能
        long size = redisTemplate.opsForZSet().size(key);
        // 删除最旧的消息,只保留最新的部分信息
        if (size > cacheSize) {
            redisTemplate.opsForZSet().removeRange(key, 0, size - cacheSize - 1);
        }
    }

    // 查询最新的 N 条消息
    // 使用 ZREVRANGE 查询最新的 N 条消息
    public Set<BasicMessage> getLatestMessages(Long receiverId) {
        String key = CacheConstants.OFFLINE_MSG + receiverId;
        return redisTemplate.opsForZSet().range(key, 0, -1);
    }

    public Set<String> getOfflineSenderId(Long receiverId) {
        String key = CacheConstants.OFFLINE_SENDER + receiverId;
        return stringRedisTemplate.opsForSet().members(key);
    }

    // 删除已读取的消息（按 ID 范围）
    // 使用 ZREMRANGEBYSCORE 删除消息范围内的消息
    public void removeReadMessages(Long receiverId, Long minMsgId, Long maxMsgId) {
        String key = CacheConstants.OFFLINE_MSG + receiverId;
        redisTemplate.opsForZSet().removeRangeByScore(key, minMsgId, maxMsgId);
    }

    // 分段存储消息（按月/周）
    // 使用 ZADD 将消息存入指定时间段的 key
    public void addMessageToSegmentedQueue(Long receiverId, Long msgId, BasicMessage msg, String timePeriod) {
        String key = CacheConstants.OFFLINE_MSG + receiverId + "_" + timePeriod;
        redisTemplate.opsForZSet().add(key, msg, msgId);
    }

    // 获取按时间段存储的最新消息
    // 使用 ZREVRANGE 查询按时间段排序的最新消息
    public Set<BasicMessage> getLatestMessagesByTimePeriod(Long receiverId, int count, String timePeriod) {
        String key = CacheConstants.OFFLINE_MSG + receiverId + "_" + timePeriod;
        return redisTemplate.opsForZSet().reverseRange(key, 0, count - 1);
    }
}
